﻿/*
 * @Autor: PK
 * @Date: 2021/12/28 09:38:SS
 */

using System;
using System.Collections.Generic;
using ShkSimulation.core.exceptions;

namespace ShkSimulation.core.dao.statistic.feature {
	
	public readonly struct DataPair : IComparable<DataPair> {
		
		public readonly double Value { get; }
		
		public readonly string UniqueKey { get;}

		private readonly bool isEmpty;

		public static DataPair Empty => new DataPair(string.Empty);
		
		public bool IsEmpty() {
			return isEmpty;
		}

		public static bool IsEmpty(DataPair dataPair) {
			return dataPair.isEmpty;
		}

		public DataPair(string uniqueKey, double value) {
			isEmpty = false;
			if (string.IsNullOrEmpty(uniqueKey)) {
				throw new ErrorParamException("数据对的key不能为空");
			}
			UniqueKey = uniqueKey;
			Value = value;
		}

		#region 默认
		
		public static DataPair operator +(DataPair inner, DataPair outter) {
			if (inner.isEmpty || outter.isEmpty) {
				return inner.isEmpty ? outter : inner;
			}
			if (!inner.UniqueKey.Equals(outter.UniqueKey)) {
				throw new ErrorParamException("不同的UniqueKey不能相加");
			}
			return new DataPair(inner.UniqueKey, inner.Value + outter.Value);
		}
		
		public static DataPair operator -(DataPair inner, DataPair outter) {
			if (inner.isEmpty || outter.isEmpty) {
				return inner.isEmpty ? outter : inner;
			}
			if (!inner.UniqueKey.Equals(outter.UniqueKey)) {
				throw new ErrorParamException("不同的UniqueKey不能相减");
			}
			return new DataPair(inner.UniqueKey, inner.Value - outter.Value);
		}
		
		public static DataPair operator *(DataPair inner, DataPair outter) {
			if (inner.isEmpty || outter.isEmpty) {
				return inner.isEmpty ? outter : inner;
			}
			if (!inner.UniqueKey.Equals(outter.UniqueKey)) {
				throw new ErrorParamException("不同的UniqueKey不能相减");
			}
			return new DataPair(inner.UniqueKey, inner.Value * outter.Value);
		}
		
		public static DataPair operator /(DataPair inner, DataPair outter) {
			if (inner.isEmpty || outter.isEmpty) {
				return inner.isEmpty ? outter : inner;
			}
			if (!inner.UniqueKey.Equals(outter.UniqueKey)) {
				throw new ErrorParamException("不同的UniqueKey不能相减");
			}
			return new DataPair(inner.UniqueKey, inner.Value / outter.Value);
		}
		
		public static bool operator ==(DataPair inner, DataPair outter) {
			return inner.Equals(outter);
		}
		
		public static bool operator !=(DataPair inner, DataPair outter) {
			return !inner.Equals(outter);
		}

		private DataPair(string uniqueKey) {
			isEmpty = true;
			UniqueKey = uniqueKey;
			Value = double.MinValue;
		}
		
		public bool Equals(DataPair other) {
			return isEmpty == other.isEmpty && Value.Equals(other.Value) && UniqueKey == other.UniqueKey;
		}

		public override bool Equals(object obj) {
			return obj is DataPair other && Equals(other);
		}

		public override int GetHashCode() {
			return HashCode.Combine(isEmpty, Value, UniqueKey);
		}

		private sealed class IsEmptyValueUniqueKeyEqualityComparer : IEqualityComparer<DataPair> {

			public bool Equals(DataPair x, DataPair y) {
				return x.isEmpty == y.isEmpty && x.Value.Equals(y.Value) && x.UniqueKey == y.UniqueKey;
			}

			public int GetHashCode(DataPair obj) {
				return HashCode.Combine(obj.isEmpty, obj.Value, obj.UniqueKey);
			}

		}

		public static IEqualityComparer<DataPair> IsEmptyValueUniqueKeyComparer { get; } = new IsEmptyValueUniqueKeyEqualityComparer();

		public int CompareTo(DataPair other) {
			return Value.CompareTo(other.Value);
		}

		private sealed class ValueRelationalComparer : IComparer<DataPair> {

			public int Compare(DataPair x, DataPair y) {
				return x.Value.CompareTo(y.Value);
			}

		}

		public static IComparer<DataPair> ValueComparer { get; } = new ValueRelationalComparer();

		public override string ToString() {
			return $"[{UniqueKey}:{Value}]";
		}

		public void Deconstruct(out string uniqueKey, out double value) {
			value = Value;
			uniqueKey = UniqueKey;
		}
		#endregion

	}

}